package com.yqxc.folkspace.util;

import com.alibaba.fastjson.JSONObject;
import org.fisco.bcos.sdk.crypto.CryptoSuite;
import org.fisco.bcos.sdk.crypto.keypair.CryptoKeyPair;
import org.fisco.bcos.sdk.crypto.keypair.ECDSAKeyPair;
import org.fisco.bcos.sdk.crypto.signature.SignatureResult;
import org.fisco.bcos.sdk.model.CryptoType;
import org.fisco.bcos.sdk.utils.Hex;
import org.springframework.stereotype.Service;

import javax.annotation.PostConstruct;

/**
 * @author 元启星辰（北京）科技有限公司
 * @describe FISCO BCOS 密钥工具类：EC密钥对生成，签名，验签
 * @date 2021-12-25
 */
@Service
public class KeyUtil {

    // FISCO BCOS 密码学模块
    private CryptoSuite cryptoSuite;
    // FISCO BCOS 交易签名模块
    private MyTransactionEncoderUtil myTransactionEncoderUtil;


    /**
     * 初始化服务
     */
    @PostConstruct
    public void init() {
        cryptoSuite = new CryptoSuite(CryptoType.ECDSA_TYPE);
        myTransactionEncoderUtil = new MyTransactionEncoderUtil(cryptoSuite);
    }

    /**
     * 生成EC密钥对
     *
     * @return 密钥对+地址的JSON
     */
    public JSONObject generateKey() {

        CryptoKeyPair cryptoKeyPair = ECDSAKeyPair.createKeyPair();

        JSONObject resultJson = new JSONObject();
        resultJson.put("privateKey", cryptoKeyPair.getHexPrivateKey());
        resultJson.put("publicKey", cryptoKeyPair.getHexPublicKey());
        resultJson.put("address", cryptoKeyPair.getAddress());

        return resultJson;
    }

    /**
     * 签名
     *
     * @param dataWithOutSign 需要签名的字符串
     * @param privateKey      私钥字符串
     * @return 签名生成的字符串
     */
    public String signData(String dataWithOutSign, String privateKey) {

        // 创建私钥对
        CryptoKeyPair myKeyPair = cryptoSuite.createKeyPair(privateKey);

        // 签名数据转字节数组
        byte[] hashMessageStr = Hex.decode(dataWithOutSign);

        // 对交易编码值签名
        SignatureResult signatureTx = myTransactionEncoderUtil.sign(hashMessageStr, myKeyPair);

        // 签名后的signedTx
        String signedData = signatureTx.convertToString();

        return signedData;
    }

    /**
     * 验签
     *
     * @param publicKey 公钥字符串
     * @param message   需要签名的字符串
     * @param signature 签名生成的字符串
     * @return 验签bool结果
     */
    public boolean verifyData(String publicKey, String message, String signature) {

        return cryptoSuite.verify(publicKey, message, signature);
    }

}
